<?php
/*
 * @Description    : WebSocketController
 * @Author         : QianLong
 * @Date           : 2023-05-04 10:39:14
 * @LastEditors    : QianLong
 * @Site           : http://www.21ds.cn
 * @LastEditTime   : 2024-05-15 17:26:47
 */

declare(strict_types=1);

namespace App\Controller;

use App\Common\RedisCache;
use Hyperf\SocketIOServer\Annotation\Event;
use Hyperf\SocketIOServer\Annotation\SocketIONamespace;
use Hyperf\SocketIOServer\BaseNamespace;
use Hyperf\SocketIOServer\Socket;
use Hyperf\Codec\Json;
use Hyperf\WebSocketServer\Context;
use Hyperf\WebSocketClient\ClientFactory;
use Hyperf\Di\Annotation\Inject;
use Hyperf\SocketIOServer\SidProvider\SidProviderInterface;
use Hyperf\WebSocketServer\Sender;

#[SocketIONamespace("/")]
class WebSocketController extends BaseNamespace
{

  #[Inject]
  protected ClientFactory $clientFactory;
  /**
   * @param string $data
   */
  #[Event("event")]
  public function onEvent(Socket $socket, $data)
  {
    $data = (is_array($data) == true) ? $data : Json::decode($data);
    // 应答
    return 'Event Received: ' . print_r($data, true);
  }

  /**
   * @param string $data
   */
  #[Event("join-room")]
  public function onJoinRoom(Socket $socket, $data)
  {
    $data = (is_array($data) == true) ? $data : Json::decode($data);
    $socketServer = Context::get('socketServer');
    $redisCache = new RedisCache;
    $room = '';
    if (isset($data['room']) && !empty($data['room'])) {
      $room = $socketServer['uid'] . '_' . $data['room'];
    }else{
      $data['room'] = '';
    }
    // 将当前用户加入房间
    if (!empty($room)) {
      $socket->join($room);
    }
    if (isset($data['union_id']) && !empty($data['union_id'])) {
      $redisCache->getSetSocketUnionId($socketServer['uid'] . '_' . $data['union_id'], $socket->getSid());
    }
    $event_name = (isset($data['event_name']) && !empty($data['event_name']))? $data['event_name']:'join-room';
    // 向房间内其他用户推送（不含当前用户）
    $sayData['sid'] = $socket->getSid();
    $sayData['room'] = $data['room'];
    if (!empty($room)) {
      $sayData['total'] = count($socket->getAdapter()->clients($room));
    }else{
      $sayData['total'] = 0;
    }
    if (!empty($room)) {
      if (isset($data['to_all']) && $data['to_all'] == 0) {
        $socket->to($room)->emit($event_name, json_encode($sayData, JSON_UNESCAPED_UNICODE));
      } else {
        // 向房间内所有人广播（含当前用户）
        $this->emit($event_name, json_encode($sayData, JSON_UNESCAPED_UNICODE));
      }
    }
    unset($data, $sayData, $socketServer);
  }

  /**
   * @param string $data
   */
  #[Event("say")]
  public function onSay(Socket $socket, $data)
  {
    $data = is_array($data)? $data:Json::decode($data);
    $socketServer = Context::get('socketServer');
    $event_name = (isset($data['event_name']) && !empty($data['event_name'])) ? $data['event_name'] : 'say';
    $toUser = '';
    $room = '';
    if (isset($data['room']) && !empty($data['room'])) {
      $room = $socketServer['uid'] . '_' . $data['room'];
    } else {
      $data['room'] = '';
    }
    if (isset($data['union_id']) && !empty($data['union_id'])) {
      $toUser = (new RedisCache)->getSetSocketUnionId($socketServer['uid'] . '_' . $data['union_id']);
    }
    $sayData['sid'] = $socket->getSid();
    $sayData['room'] = $data['room'];
    if (empty($toUser)) {
      $toUser = $room;
    }
    $sayData['message'] = $data['message'];
    if (isset($data['to_all']) && $data['to_all'] == 0) {
      $socket->to($toUser)->emit($event_name, json_encode($sayData, JSON_UNESCAPED_UNICODE));
    } else if(!empty($room)) {
      // 向房间内所有人广播（含当前用户）
      $this->to($room)->emit($event_name, json_encode($sayData, JSON_UNESCAPED_UNICODE));
    }
    unset($data,$sayData, $socketServer);
  }
}
